#include "show.h"

#include "bt.h"
#include "mpu6050.h"
#include "oled.h"
#include "ws2812.h"

#undef Handler
#define Handler Show_HandleTypeDef*

#undef handler
#define handler (**(Show_HandleTypeDef**)&handle)

void Show_Init(void* handle) {
  Oled_ClearAll();
  Oled_ShowStringBig(0, 0, "      SHOW      ");
  Bt_Init(Show_M_L, NULL, NULL, Show_M_O,    // M
          NULL, NULL, NULL, NULL,            // U
          NULL, NULL, NULL, NULL,            // D
          Show_L_LJ, NULL, Show_L_LJ, NULL,  // L
          Show_R_LJ, NULL, Show_R_LJ, NULL,  // R
          100);
  handler.into = 0;
  handler.outo = 0;
  handler.lock = 1;
  handler.offsetByYaw = 0;
  handler.offsetByBt = 0;
  handler.yaw = 0;
  handler.vz = 1;
  handler.dt = 0;

  if (Mpu_Init()) {
    Oled_ClearAll();
    Oled_ShowStringBig(0, 0, "MPU6050 INIT ERR");
    HAL_Delay(1000);
    handler.outo = 1;
  } else {
    Show_InitShow(handle);
  }
  while (hbt.bu & BU_M) Bt_Update();
}

void Show_InitShow(void* handle) {
  Oled_ClearAll();
  turn = 0xFF;
  Oled_ShowStringBig(0, 0, "      SHOW      ");
  turn = 0x00;
  Oled_ShowStringSmall(0, 2, "Yaw(+180):");
  Oled_ShowStringSmall(0, 3, "VZ(*100+100):");
  Oled_ShowStringSmall(0, 4, "offset:");
  Oled_ShowStringSmall(0, 5, "reserve:");
  Oled_ShowStringSmall(0, 6, "Lock:");
  Show_ShowDate(handle);
}

void Show_ShowDate(void* handle) {
  Oled_ShowNumSmall(110, 2, (uint16_t)(handler.yaw + 180), 3);
  Oled_ShowNumSmall(110, 3, (uint16_t)(handler.vz * 100 + 100), 3);
  Oled_ShowNumSmall(110, 4, (uint16_t)(hws.offset), 3);
  if (hws.reserve) {
    Oled_ShowStringSmall(110, 5, " on");
  } else {
    Oled_ShowStringSmall(110, 5, "off");
  }
  if (handler.lock) {
    Oled_ShowStringSmall(110, 6, " on");
  } else {
    Oled_ShowStringSmall(110, 6, "off");
  }
}

void Show_Run(void* handle) {
  if (handler.outo) {
    return;
  }
  while (1) {
    Bt_Update();
    Bt_Run(handle);

    // 更新WS2812, 高达20Hz的刷新率
    if (hbt.time.now - handler.dt > 50) {
      // 更新MPU6050
      Mpu_Update(&hmpu);
      Mpu_GetYaw(&hmpu, &handler.yaw);
      Mpu_GetVZ(&hmpu, &handler.vz);
      if (!handler.lock) {
        // handler.offsetByBt +=
        //     handler.offsetByYaw - (uint8_t)(32.0 * (handler.yaw + 180) /
        //     360);
        handler.offsetByYaw = (uint8_t)(32.0 * (handler.yaw + 180) / 360);
        // 设置是否上下反向
        if (handler.vz > 0)
          hws.reserve = 0;
        else
          hws.reserve = 1;
      }
      hws.offset = (handler.offsetByBt + 16 + handler.offsetByYaw) % 32;

      Ws_Load(hws.matrix.color);
      Ws_Draw();
      handler.dt = hbt.time.now;
    }
    // 更新oled
    Show_ShowDate(handle);
    if (handler.outo) {
      return;
    }
  }
}

void Show_M_L(void* handle) { handler.outo = 1; }
void Show_M_O(void* handle) { handler.lock = ~handler.lock; }
void Show_L_LJ(void* handle) {
  if (handler.offsetByBt < 31) {
    handler.offsetByBt++;
  } else {
    handler.offsetByBt = 0;
  }
  Show_ShowDate(handle);
}
void Show_R_LJ(void* handle) {
  if (handler.offsetByBt > 0) {
    handler.offsetByBt--;
  } else {
    handler.offsetByBt = 31;
  }
  Show_ShowDate(handle);
}
